#ifndef _BOOTLOADER_DEVICE_RESOURCE_H_
#define _BOOTLOADER_DEVICE_RESOURCE_H_
#include "ParameterStoreDPT.h"
/* --------------------------------------------------------------------------------------------------
 * @name:  BREAK_UINT32
 *
 * @brief：从uint32_t变量中取出一个uint8_t的内容
 *
 * @param: var       - 类型为uint32_t的变量
 *         byte_num  - 取值位置 (0-3)
 *
 * @note ：uint8_t test = BREAK_UINT32(0x12345678, 3)  //test的值为0x12
 *         uint8_t test = BREAK_UINT32(0x12345678, 2)  //test的值为0x34
 *         uint8_t test = BREAK_UINT32(0x12345678, 1)  //test的值为0x56
 *         uint8_t test = BREAK_UINT32(0x12345678, 0)  //test的值为0x78
 */
#define BREAK_UINT32(var, byte_num) (uint8_t)((uint32_t)(((var) >> ((byte_num) * 8)) & 0x00FF))

/* --------------------------------------------------------------------------------------------------
 * @name:  BUILD_UINT32
 *
 * @brief：把4个uint8_t变量组成一个uint32_t变量
 *
 * @param: byte0 - uint8_t型变量0
 *         byte1 - uint8_t型变量1
 *         byte2 - uint8_t型变量2
 *         byte3 - uint8_t型变量3
 *
 * @note ：uint32_t test = BUILD_UINT32(0x78, 0x56, 0x34, 0x12)  //test的值为0x12345678
 */
#define BUILD_UINT32(byte0, byte1, byte2, byte3) ((uint32_t)((uint32_t)((byte0) & 0x00FF) + ((uint32_t)((byte1) & 0x00FF) << 8) + ((uint32_t)((byte2) & 0x00FF) << 16) + ((uint32_t)((byte3) & 0x00FF) << 24)))

/* --------------------------------------------------------------------------------------------------
 * @name:  BUILD_UINT16
 *
 * @brief：把2个uint8_t变量组成一个uint16_t变量
 *
 * @param: low_byte   - uint8_t型变量低字节
 *         high_byte  - uint8_t型变量高字节
 *
 * @note ：uint16_t test = BUILD_UINT16(0x34, 0x12)  //test的值为0x1234
 */
#define BUILD_UINT16(low_byte, high_byte) ((uint16_t)(((low_byte) & 0x00FF) + (((high_byte) & 0x00FF) << 8)))

/* --------------------------------------------------------------------------------------------------
 * @name:  BUILD_UINT8
 *
 * @brief：把2个4位变量组成一个uint8_t变量
 *
 * @param: high_byte   - 高半字节
 *         low_byte    - 低半字节
 *
 * @note ：uint16_t test = BUILD_UINT16(0x34, 0x12)  //test的值为0x1234
 */
#define BUILD_UINT8(high_byte, low_byte) ((uint8)(((low_byte) & 0x0F) + (((high_byte) & 0x0F) << 4)))

#define HI_UINT16(a) (((a) >> 8) & 0xFF) // 取16位的高8位
#define LO_UINT16(a) ((a) & 0xFF)        // 取16位的低8位

#define HI_UINT8(a) (((a) >> 4) & 0x0F) // 取8位的高4位
#define LO_UINT8(a) ((a) & 0x0F)        // 取8位的低4位

#define MAX(a, b)     (((a) < (b)) ? (b) : (a))               // 取较大者
#define MIN(a, b)     (((a) < (b)) ? (a) : (b))               // 取较小者
#define MAX3(a, b, c) ((MAX(a, b) < (c)) ? (c) : (MAX(a, b))) // 三个数取最大者
#define MIN3(a, b, c) ((MIN(a, b) < (c)) ? (MIN(a, b)) : (c)) // 三个数取最小者

#define ABS(n) (((n) < 0) ? -(n) : (n)) // 绝对值

#define ARR_SIZE(a) (sizeof((a)) / sizeof((a[0]))) // 返回数组元素的个数, a为数组名

#define BITSET(var, bitno) ((var) |= (1 << (bitno)))  // 把var的第bitno位置1
#define BITCLR(var, bitno) ((var) &= ~(1 << (bitno))) // 把var的第bitno位置0
#define BITTST(var, bitno) (var & (1 << (bitno)))     // 获得var的第bitno位置数值，是0还是1

#define BCD_to_HEC(b) (((b >> 4) * 10) + (b & 0x0f))
#define HEC_to_BCD(h) (((h / 10) << 4) | (h % 10))

// 每毫秒所需空操作数（168 MHz 下经验值，可实测微调）
#define LOOP_PER_MS (uint32_t)(168000UL / 4) /* 4 条 NOP 算一次循环 */

/* 单毫秒阻塞 */
#define DELAY_1MS()             \
  do                            \
  {                             \
    uint32_t cnt = LOOP_PER_MS; \
    while (cnt--)               \
    {                           \
      __NOP();                  \
    }                           \
  } while (0)

/* 任意毫秒阻塞 */
#define DELAY_MS(ms)     \
  do                     \
  {                      \
    uint32_t _ms = (ms); \
    while (_ms--)        \
    {                    \
      DELAY_1MS();       \
    }                    \
  } while (0)

// BIT0:SRAM ERROR
// BIT1:RTL8372  ERROR
// BIT2:W6100 ERROR
// BIT3:LAN8720A ERROR
// BIT4:SPI-FLASH ERROR
// BIT5:E2PROM ERROR
// BIT6:RTC ERROR
// BIT7:UART ERROR
typedef enum
{
  SRAM_ERROR = 0x00,
  RTL8372_ERROR,
  W6100_ERROR,
  LAN8720A_ERROR,
  SPI_FLASH_ERROR,
  E2PROM_ERROR,
  RTC_ERROR,
  UART_ERROR,
  SFP_ERROR,
  ERROR_CODE_MAX
} ERROR_CODE_BIT;

extern struct ParameterStoreDPT setting_para;

#endif

